package com.jh.fcsm.common.mybatis;

import com.jh.fcsm.beans.sys.vo.LoginUser;
import com.jh.fcsm.constant.Constant;
import com.jh.fcsm.util.AppUserUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
import java.util.Properties;

/**
 * MyBatis 新增和修改拦截-添加新增或修改用户信息及时间
 */
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class OpeInfoInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger(OpeInfoInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object parameter = args[1];

        // 增删改调用update方法，共2个参数
        if (args.length == 2) {
            // 如果是map，有两种情况：（1）使用@Param多参数传入，由Mybatis包装成map。（2）原始传入Map
            if (parameter instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<Object, Object> map = (Map<Object, Object>) parameter;
                for (Object obj : map.values()) {
                    invokeUpdate(ms, obj);
                }
            } else {
                invokeUpdate(ms, parameter);
            }
        }
        return invocation.proceed();

    }

    /**
     * 数据库更新操作
     *
     * @param ms        MappedStatement
     * @param parameter 数据对象或者Map对象
     */
    private void invokeUpdate(MappedStatement ms, Object parameter) {
        SqlCommandType commandType = ms.getSqlCommandType();
        LoginUser loginUser = getLoginUser();

        try {
            if (SqlCommandType.INSERT == commandType) {
                BeanUtils.setProperty(parameter, "createUser", loginUser.getUsername());
                BeanUtils.setProperty(parameter, "createUserNickname", loginUser.getNickname());
                BeanUtils.setProperty(parameter, "createTime", new Date());
                BeanUtils.setProperty(parameter, "yn", Constant.YES);
            }

            if (SqlCommandType.INSERT == commandType || SqlCommandType.UPDATE == commandType) {
                BeanUtils.setProperty(parameter, "updateUser", loginUser.getUsername());
                BeanUtils.setProperty(parameter, "updateUserNickname", loginUser.getNickname());
                BeanUtils.setProperty(parameter, "updateTime", new Date());
            }
        } catch (Exception e) {
            logger.error("统一处理公共字段发生错误", e);
        }
    }

    /**
     * 获取当前登录用户信息
     *
     * @return 用户
     */
    private LoginUser getLoginUser() {
        LoginUser loginUser = (LoginUser) AppUserUtil.getLoginAppUser();
        if (null == loginUser) {
            loginUser = new LoginUser();
        }
        return loginUser;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

}
